LS FORTRAN 3.3
Volume 9
Number 11
Column Tag Jörg's Folder
Language Systems FORTRAN 3.3 
Performance test & FORTRAN to C conversion
By Jörg Langowski, MacTech Magazine Regular Contributing Author
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
Since Absoft has just brought out a new Fortran compiler (see July column,
MacFORTRAN 3.2), the competition wasn’t sleeping: as I told you in my last column, Language Systems has brought out version 3.3 of their Fortran. It’s now installed (I
got it the day I sent off the last column) and here are the Benchmark figures. Note: All
benchmark tests were run at optimization level 3 for the LS Fortran compiler and at
level -O (i.e. basic optimizations but no loop unrolling and subroutine folding) for the
Absoft compiler. First, the results of the Linpack program for LS Fortran 3.3:
Linpack performance, single precision
LSF 3.3 MacIIx 0.125 MFlops
Q700, 68030 code 1.33 MFlops
Q700, 68040 code 1.33 MFlops
These performances are exactly the same as for version 3.0.1. It is interesting
that it makes no difference at all whether 68030 or 68040 code is generated; it seems
that the Absoft compiler is still making better use of the 68040 specifics. For
example, Absoft MacFortran v3.3 runs the same code at 1.30 MFlops on a Quadra 700
when 68030 code is generated (thus at the same speed as LS Fortran) and at 1.61
MFlops for native 68040 code, i.e. 25% faster.
Language Systems has added a faster transcendental function library for the
68040, however. Since the Linpack does not use transcendental functions, this feature
is not tested. Another known program, the Savage benchmark, tests accuracy and speed
of some built-in math functions (see listing). The results, comparing the latest
versions of the LS and Absoft compilers:
Savage Benchmark (execution times and results)
LSF 3.3 MacIIx 3.60 s 2500.000
Q700, 68030 code 3.02 s 2500.000
Q700, 68040 code 1.80 s 2500.000
Absoft MacIIx 3.52 s 2499.886
extended precision 3.65 s 2500.000
Q700, 68030 code 3.23 s 2499.886
Q700, 68040 code 1.37 s 2477.244
Q700, double precision
68040 code 1.43 s 2500.000
One thing that is immediately evident is the shabby performance of the 68040 on
68030 code; the Quadra 700 is no faster here than a Mac IIx! But this comes as no
surprise: the 68040 FPU has no transcendental functions and EXP, LOG, etc. must be
emulated in software. The 68040 math libraries of both LS and Absoft Fortran are
much faster than the Apple emulation. For Absoft on the 68040, you have to take care
that you compile with the ‘double precision transcendentals’ option, on the 68040, or
with the extended precision option on the 68030, otherwise precision really breaks
down. On the 68030, two compilers have identical performance speed- and
precision-wise on the Savage benchmark. On the 68040, Absoft again has the speed
edge over LS Fortran by about 30%.
So it is fair to say that Absoft’s compiler still produces the fastest-running
Fortran code for the 68040; however, when you port programs from other systems,
you should be very careful in checking the numerical accuracy against known results.
Or play it safe in any case by using default double or extended precision, which doesn’t
slow down execution too much.
To save the honor of the Macintosh, one should say that on so-called ‘bigger’
systems you have similar problems: for instance, on a VAX or on a Silicon Graphics
workstation you have to declare A double precision to get the correct answer of
2500.000.
It seems at the moment that the Fortran compilers for the Macintosh are at a
stage where they have converged to their respective limits of performance, and both
are very similar speed- and precision-wise except for Absoft’s higher speed on a
68040. On the other hand, LS Fortran is still the only compiler that creates code to
run on systems without an FPU. I guess what one should expect next from Language
Systems is that they work on their Macintosh interface, for instance it would be nice to
have multiple output windows connected to Fortran units.
Fortran to C
For those of you who have inherited some thousand lines of Fortran code and want
to port it to the Mac, there may still be another way to go than using one of those
excellent Fortran compilers. Even though Fortran is much better than its reputation
with some people (you just have to look at the code provided by Language Systems of
Absoft for full Macintosh applications), you might prefer to put in the work of
converting your whole program into C, or C++. It is true that you may can gain a lot in
readability and maintainability this way; but that mountain of work rewriting the
code
Well, if you want to give up your Fortran nostalgia and like the fast compile/test
cycle that Think C offers (there is no Think Fortran), here is a program for you: f2c,
a public domain Fortran-to-C translator that has been around on Unix systems for
quite a while. Some time ago, Basil Duval from Switzerland took the time to convert
this program to Think C and put the result into the public domain Info-Mac archives at
Stanford. His README file explains what he did:
“IMPORTANT--- This file and the others are available via anonymous ftp on
elpp1.epfl.ch.
f2c Conversion on the MAC
Basil P. Duval Jan 1992, EPFL/CRPP Bassenges 1015 Lausanne, Switzerland
(This software is submitted free of change and may not be sold)
Email: Duval@elpp1.epfl.ch
Subject
This note describes a port of f2c to the THINK C Mac environment. The program f2c and
the libraries libI77 and libF77 were converted and fortran programs have been
successfully translated and linked to form working applications. In this first port, the
default THINK C standard "Glass Window" screen is used to perform user input and
output.
Version converted
The version taken from the server re search.att.edu the 9 jan 1992 and has the 30
december 1991 time stamp.
Environment
The main problem with the port from UNIX to the Mac has been the 32k limit on
global variables present up to version 5 of THINK C. Version 4 of THINK C allows
string variables to be placed in a separate section. by simply requesting this option in
the project options, the global variables were reduced from 56k to 31.6k which is
acceptable in the Mac environment. Thus the program could be linked and tested. This
enabled other problems of the port to surface. The main problem is due to the confusion
with short and long integers. Up to THINK C 4, short was always defined as 2 bytes. In
particular this causes several bugs when using the "strn..." functions which expect a
(long) integer and as the code arrived were only given a 2 byte (short). The last
problem was to provide a simple user interface. THINK C provides a console library
which emulates the UNIX style command line via the "ccommand" routine which has
been used to provide a rudimentary, but serviceable, interface. A list of the files that
were changed is provided and the details of each change are provided at the end of this
note.
(details omitted-JL)
Enclosed is a complete translation of the source using THINK C 5.02 together with
a test file temp.f and a test project. The application has been compiled and linked for a
Mac with 68030 and 68882 FPU unit but with the projects this could easily be
changed. I spend the time since you mailed me getting the latest version of the f2c and
putting in the bits needed to make it fly on the Mac, and so this version is labelled May
1992.
Good luck. The C source code is not supposed to be easy to edit, but it does get you
quite a long way from the Fortran.
Basil Duval 2 June 1992
PS:Language Systems Fortran together with MPW 3.2 is a great combination if
you decide to stay in fortran. THINK C is however a great environment for the Mac....”
The ready-to-use f2c application will be on the source code disk; for space
reasons we cannot distribute the full system. If you have Internet access, you can
however get the files via ftp either from the address given in the README file (see
above), or from the Info-Mac archives at sumex-aim.stanford.edu. The conversion of
the Savage benchmark is enclosed as an example in Listing 2. Of course you could have
done this better by hand - however when you’re dealing with 4000 lines of code, that’s
another story. I’ll try my hands on one of the big programs I have here until the next
column and tell you my experiences - but first I have to get familiar with Think C,
which I have never seriously used, believe it or not. Until then.
Listing 1: Savage Benchmark
C SAVAGE BENCHMARK
REAL*4 A
C SECNDS is a real*4 function that returns
C seconds and fractional seconds. The value is
C modified by subtracting the supplied argument.
C It acts as in the VMS FORTRAN Manual.
real*4 SECNDS
real*4 time
write(*,*) 'Starting'
time = SECNDS(0.0)
DO 200 J=1,10
A=1.0D0
DO 100 I=1,2499
A=TAN(ATAN(EXP(LOG(SQRT(A*A))))) + 1.0
100 CONTINUE
200 CONTINUE
time = SECNDS(time)
WRITE (*,10) A
10 FORMAT(' A=',F17.12)
write(*,*) time,' seconds'
PAUSE
END
REAL FUNCTION SECNDS(time)
real time
n = LONG(362)
SECNDS = FLOAT(n)/60.0 - time
END
Listing 2: Savage Benchmark, converted to C by the f2c translator
/* -- translated by f2c (version of 23 May 1992 14:18:33).
You must link the resulting object file with the libraries:
-lF77 -lI77 -lm -lc (in that order)
*/
#include "f2c.h
/* Table of constant values */
static integer c__9 = 9;
static integer c__1 = 1;
static real c_b4 = (float)0.;
static integer c__4 = 4;
/* !MP inlines.f */
/* SAVAGE BENCHMARK */
/* Main program */ MAIN__()
{
/* Format strings */
static char fmt_10[] = "(\002 A=\002,f17.12)";
/* Builtin functions */
integer s_wsle(), do_lio(), e_wsle();
double sqrt(), log(), exp(), atan(), tan();
integer s_wsfe(), do_fio(), e_wsfe();
/* Local variables */
static real time, a;
static integer i, j;
extern doublereal secnds_();
/* Fortran I/O blocks */
static cilist io___1 = { 0, 6, 0, 0, 0 };
static cilist io___6 = { 0, 6, 0, fmt_10, 0 };
static cilist io___7 = { 0, 6, 0, 0, 0 };
/* SECNDS is a real*4 function that returns */
/* seconds and fractional seconds. The value is */
/* modified by subtracting the supplied argument. */
/* It acts as in the VMS FORTRAN Manual. */
s_wsle(&io___1);
do_lio(&c__9, &c__1, "Starting\311", 9L);
e_wsle();
time = secnds_(&c_b4);
for (j = 1; j <= 10; ++j) {
a = (float)1.;
for (i = 1; i <= 2499; ++i) {
a = tan(atan(exp(log(sqrt(a * a))))) + (float)1.;
/* L100: */
}
/* L200: */
}
time = secnds_(&time);
s_wsfe(&io___6);
do_fio(&c__1, (char *)&a, (ftnlen)sizeof(real));
e_wsfe();
s_wsle(&io___7);
do_lio(&c__4, &c__1, (char *)&time, (ftnlen)sizeof(real));
do_lio(&c__9, &c__1, " seconds", 8L);
e_wsle();
} /* MAIN__ */